home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 11 / Cream of the Crop 11-1.iso / games / text_eng.zip / TEXTURE.C < prev    next >
C/C++ Source or Header  |  1995-12-12  |  36KB  |  1,169 lines

  1. /*
  2.  *    TEXTURE.C    Version 1.0   by Lee Lorenz      llorenz@delphi.com
  3.  *
  4.  *   First, Please excuse this mess.
  5.  *
  6.  *  Next, Welcome to high-speed image processing... My desire was to
  7.  *   rotate/scale a bitmap in real-time, and this was the result.
  8.  *   There were plenty of "examples" of texture mapping, in obfuscated
  9.  *   highly optimized assembly, but even the "C" and Pascal examples left
  10.  *   alot to be desired; after all, I wanted to have more freedom to display
  11.  *   images, and didn't want to bother with the trigonometry. With the simple
  12.  *   idea of "shooting" a line (Bresenham-style) through a source bitmap, I
  13.  *   developed this technique contained in DrawTexture. It may not be original,
  14.  *   but I haven't seen it used anywhere else. It can even be augmented with
  15.  *   anti-aliasing for image processing. I release this program and technique
  16.  *   into the public domain, and I hope to create a highly optimized 386
  17.  *   assembler version for my personal library. Please try to credit me when
  18.  *   possible, if this shows you anything new or interesting, and you use it
  19.  *   in any distributed program (Freeware/shareware/commercial).
  20.  *
  21.  *   What this program does:
  22.  *    Draws a bitmap into any 4-sided polygon. First vector is upper-left
  23.  *    second is upper-right, third is lower-right, and last is lower-left.
  24.  *
  25.  *   Limitations:
  26.  *    Don't try to use a "Horizontally convex" polygon.
  27.  *    Undefined results with intersected polygons
  28.  *
  29.  *   What remains to be done:
  30.  *    1. A good intersection-detection routine.
  31.  *    2. A quick 2-D rotation/scaling transform for the corners. I want to
  32.  *       be able to "spin" the bitmap/sprite about a point.
  33.  *    3. Possible, slower alternative to scan "horizontal convex" polygons
  34.  *       and intersected polygons
  35.  *
  36.  */
  37.  
  38. #include <stdio.h>
  39. #include <malloc.h>
  40. #include <string.h>
  41. #include <stdlib.h>
  42. #include <bios.h>
  43. #include <dos.h>
  44. #include <grx.h>
  45. #include <mousex.h>
  46. #include <time.h>
  47. #include <gif_lib.h>
  48.  
  49. int YZSize;
  50.  
  51. struct
  52. {
  53.     char filename[80];
  54.     int  sizex;
  55.     int  sizey;
  56.     unsigned char *buff;
  57.     unsigned char *pal;
  58. } slots[64];
  59.  
  60.  
  61. struct text_s
  62. {
  63.     unsigned char *Buffer;
  64.     int XSize,YSize;
  65. } MyMap;
  66.  
  67.  
  68. struct quad_s
  69. {
  70.     int x[4],y[4];
  71. } MyPoly;
  72.  
  73. void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug);
  74.  
  75. void OrderPoly(struct quad_s *poly,unsigned char *order);
  76.  
  77. /* This routine eliminates intersections by swapping corners
  78.  * if an intersection exists...
  79.  * "adjacent" segments, by nature, cannot intersect, therefore we only
  80.  * need to check opposite segments (AB,CD & DA,BC)
  81.  * Actually, in retrospect, the poly cannot have "horizontal convexity"
  82.  * That is, the scan algorithm cannot handle more than one chunk, Our
  83.  * test, there for is for opposite corners _NOT_ to be next to one another
  84.  * when ordered...
  85.  */
  86. void UnIntersectQuad(struct quad_s *poly)
  87. {
  88.     unsigned char work_order[4];
  89.     int i;
  90.  
  91.     OrderPoly(poly,work_order);
  92.     /* Top Convexity/intersection */
  93.     switch(work_order[0])
  94.     {
  95.         case 0: /* Test to insure 2 is not adjacent */
  96.             if(work_order[1]==2)
  97.             {
  98.                 /* Swap 1 and 2 */
  99.                 i=poly->x[1];
  100.                 poly->x[1]=poly->x[2];
  101.                 poly->x[2]=i;
  102.                 i=poly->y[1];
  103.                 poly->y[1]=poly->y[2];
  104.                 poly->y[2]=i;
  105.             }
  106.             break;
  107.         case 1: /* Test to insure 3 is not adjacent */
  108.             if(work_order[1]==3)
  109.             {
  110.                 /* Swap 0 and 3 */
  111.                 i=poly->x[0];
  112.                 poly->x[0]=poly->x[3];
  113.                 poly->x[3]=i;
  114.                 i=poly->y[0];
  115.                 poly->y[0]=poly->y[3];
  116.                 poly->y[3]=i;
  117.             }
  118.             break;
  119.         case 2: /* Test to insure 0 is not adjacent */
  120.             if(work_order[1]==0)
  121.             {
  122.                 /* Swap 1 and 2 */
  123.                 i=poly->x[1];
  124.                 poly->x[1]=poly->x[2];
  125.                 poly->x[2]=i;
  126.                 i=poly->y[1];
  127.                 poly->y[1]=poly->y[2];
  128.                 poly->y[2]=i;
  129.             }
  130.             break;
  131.         case 3: /* Test to insure 1 is not adjacent */
  132.             if(work_order[1]==1)
  133.             {
  134.                 /* Swap 0 and 3 */
  135.                 i=poly->x[0];
  136.                 poly->x[0]=poly->x[3];
  137.                 poly->x[3]=i;
  138.                 i=poly->y[0];
  139.                 poly->y[0]=poly->y[3];
  140.                 poly->y[3]=i;
  141.             }
  142.             break;
  143.     }
  144.     OrderPoly(poly,work_order);
  145.     /* BOTTOM Convexity/intersection */
  146.     switch(work_order[3])
  147.     {
  148.         case 0: /* Test to insure 2 is not adjacent */
  149.             if(work_order[2]==2)
  150.             {
  151.                 /* Swap 1 and 2 */
  152.                 i=poly->x[1];
  153.                 poly->x[1]=poly->x[2];
  154.                 poly->x[2]=i;
  155.                 i=poly->y[1];
  156.                 poly->y[1]=poly->y[2];
  157.                 poly->y[2]=i;
  158.             }
  159.             break;
  160.         case 1: /* Test to insure 3 is not adjacent */
  161.             if(work_order[2]==3)
  162.             {
  163.                 /* Swap 0 and 3 */
  164.                 i=poly->x[0];
  165.                 poly->x[0]=poly->x[3];
  166.                 poly->x[3]=i;
  167.                 i=poly->y[0];
  168.                 poly->y[0]=poly->y[3];
  169.                 poly->y[3]=i;
  170.             }
  171.             break;
  172.         case 2: /* Test to insure 0 is not adjacent */
  173.             if(work_order[2]==0)
  174.             {
  175.                 /* Swap 1 and 2 */
  176.                 i=poly->x[1];
  177.                 poly->x[1]=poly->x[2];
  178.                 poly->x[2]=i;
  179.                 i=poly->y[1];
  180.                 poly->y[1]=poly->y[2];
  181.                 poly->y[2]=i;
  182.             }
  183.             break;
  184.         case 3: /* Test to insure 1 is not adjacent */
  185.             if(work_order[2]==1)
  186.             {
  187.                 /* Swap 0 and 3 */
  188.                 i=poly->x[0];
  189.                 poly->x[0]=poly->x[3];
  190.                 poly->x[3]=i;
  191.                 i=poly->y[0];
  192.                 poly->y[0]=poly->y[3];
  193.                 poly->y[3]=i;
  194.             }
  195.             break;
  196.     }
  197.     /* Now for intersection test... */
  198.  
  199. }
  200.  
  201.  
  202. int LoadSlot(int sl,char *fname);
  203. void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b);
  204.  
  205. int lastlength,lastdelta;
  206.  
  207. unsigned char *ScreenPtr;
  208.  
  209. struct Pal_s
  210. {
  211.     unsigned char Red;
  212.     unsigned char Blue;
  213.     unsigned char Green;
  214. };
  215.  
  216.  
  217. /*
  218.  
  219. This algorithm is based on the calculation of the third side of a triangle
  220. given the known two sides are connected by a right angle.
  221. This formula is: a^2+b^2=c^2. a and b are the absolute X-Y deltas.
  222. The first calcluation of c then becomes a, and Z delta becomes b,
  223. and we do it again. While we _HAVE_ to calculate the squares, it is not needed
  224. to calc the roots.
  225.  
  226. i.e. Deltas of 1+1+5=7, 1+2+4=7, but distance is less on second...
  227.                 27        21
  228.  
  229. Thus, we simply add the squares of all of the absolute deltas.
  230.  
  231. */
  232. int FindBestMatch(struct Pal_s *Pal,int r,int g,int b)
  233. {
  234.     int Distance,i,j,k,R,G,B;
  235.  
  236.     k=12288; j=0;
  237.     for(i=0;i<256;i++)
  238.     {
  239.         R=abs(Pal[i].Red-r);
  240.         R*=R;
  241.         G=abs(Pal[i].Green-g);
  242.         G*=G;
  243.         B=abs(Pal[i].Blue-b);
  244.         B*=B;
  245.         Distance=R+G+B;
  246.         if(Distance<k)
  247.         {
  248.             j=i; k=Distance;
  249.         }
  250.     }
  251.     return(j);
  252. }
  253.  
  254. /*
  255.  
  256. A simple routine to draw a four-sided polygon in a given color.
  257.  
  258. */
  259. void DrawPoly(struct quad_s *Poly,int c)
  260. {
  261.     GrLine(Poly->x[0],Poly->y[0],Poly->x[1],Poly->y[1],c);
  262.     GrLine(Poly->x[1],Poly->y[1],Poly->x[2],Poly->y[2],c);
  263.     GrLine(Poly->x[2],Poly->y[2],Poly->x[3],Poly->y[3],c);
  264.     GrLine(Poly->x[3],Poly->y[3],Poly->x[0],Poly->y[0],c);
  265.     GrPlot(Poly->x[0],Poly->y[0],c);
  266. }
  267.  
  268. unsigned char Order[4];
  269. int WhiteColor,RedColor,BlackColor,GrayColor;
  270. int rcount,lcount,rva[8],rvb[8],lva[8],lvb[8],rcnt[8],lcnt[0];
  271.  
  272. #define ROTATIONS  30
  273.  
  274. /* I wish DJGPP had a decent random macro!!!!
  275.  *  I'll get a 32-bit version done soon
  276.  */
  277. #define RAND(x)  (rand()%x)
  278.  
  279. int NewDir(int x,int y,int olddir);
  280. int UpdateX(int x,int direction);
  281. int UpdateY(int y,int direction);
  282.  
  283. void main(void)
  284. {
  285.     long DeltaX,DeltaY,XSize,YSize;
  286.     int i,j,k,NewY;
  287.     GrContext ScrCtx;
  288.     unsigned char *RPtr;
  289.     unsigned char *BuffPtr;
  290.  
  291.     for(i=0;i<64;i++)
  292.     {
  293.         slots[i].filename[0]=0;
  294.         slots[i].pal=NULL;
  295.         slots[i].buff=NULL;
  296.         slots[i].sizex=0;
  297.         slots[i].sizey=0;
  298.     }
  299.     GrSetMode(GR_default_graphics);
  300.     LoadSlot(0,"bnbtitle.gif");
  301.     MyMap.Buffer=slots[0].buff;
  302.     MyMap.XSize=slots[0].sizex;
  303.     MyMap.YSize=slots[0].sizey;
  304.     for(i=0;i<256;i++)
  305.     {
  306.         slots[0].pal[i*3]/=4;
  307.         slots[0].pal[(i*3)+1]/=4;
  308.         slots[0].pal[(i*3)+2]/=4;
  309.         setcolor(i,
  310.             slots[0].pal[i*3],
  311.                 slots[0].pal[(i*3)+1],
  312.                     slots[0].pal[(i*3)+2]);
  313.     }
  314.     WhiteColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,63,63);
  315.     RedColor=FindBestMatch((struct Pal_s *)slots[0].pal,63,13,13);
  316.     BlackColor=FindBestMatch((struct Pal_s *)slots[0].pal,0,0,0);
  317.     GrayColor=FindBestMatch((struct Pal_s *)slots[0].pal,30,30,30);
  318.     GrSaveContext(&ScrCtx);
  319.     ScreenPtr=ScrCtx.gc_baseaddr;
  320.     RPtr=ScreenPtr;
  321.     XSize=slots[0].sizex*65536;
  322.     YSize=slots[0].sizey*65536;
  323.     DeltaX=XSize/GrSizeX();
  324.     DeltaY=YSize/GrSizeY();
  325.     j=0;
  326.     DeltaX=XSize/(GrSizeX());
  327.     RPtr=ScreenPtr;
  328.     j=0;
  329.     memset(RPtr,0,GrSizeX()*GrSizeY());
  330.     DeltaX=XSize/GrSizeX();
  331.     RPtr=ScreenPtr;
  332.     memset(ScreenPtr,BlackColor,GrSizeX()*GrSizeY());
  333.     MyPoly.x[0]=GrSizeX()/10;
  334.     MyPoly.x[1]=GrSizeX()-(GrSizeX()/15);
  335.     MyPoly.x[2]=GrSizeX()-(GrSizeX()/5);
  336.     MyPoly.x[3]=GrSizeX()/12;
  337.     MyPoly.y[0]=GrSizeY()/20;
  338.     MyPoly.y[1]=GrSizeY()/10;
  339.     MyPoly.y[2]=GrSizeY()-(GrSizeY()/15);
  340.     MyPoly.y[3]=GrSizeY()-(GrSizeY()/25);
  341.     DrawPoly(&MyPoly,WhiteColor);
  342.     DrawTexture(&MyPoly,&MyMap,0);
  343.     while(!kbhit())
  344.     {
  345.         rand();
  346.         for(i=0;i<ROTATIONS;i++)
  347.         {
  348.             rand();
  349.             if(kbhit())
  350.                 break;
  351.             MyPoly.x[0]=(GrMaxX()*(i+1))/ROTATIONS;
  352.             MyPoly.x[1]=GrMaxX();
  353.             MyPoly.x[2]=GrMaxX()-(GrMaxX()*(i+1))/ROTATIONS;
  354.             MyPoly.x[3]=0;
  355.             MyPoly.y[0]=0;
  356.             MyPoly.y[1]=(GrMaxY()*(i+1))/ROTATIONS;
  357.             MyPoly.y[2]=GrMaxY();
  358.             MyPoly.y[3]=GrMaxY()-(GrMaxY()*(i+1))/ROTATIONS;
  359.             DrawPoly(&MyPoly,RedColor);
  360.             DrawTexture(&MyPoly,&MyMap,0);
  361.         }
  362.         for(i=0;i<ROTATIONS;i++)
  363.         {
  364.             rand();
  365.             if(kbhit())
  366.                 break;
  367.             MyPoly.x[3]=(GrMaxX()*(i+1))/ROTATIONS;
  368.             MyPoly.x[0]=GrMaxX();
  369.             MyPoly.x[1]=GrMaxX()-(GrMaxX()*(i+1))/ROTATIONS;
  370.             MyPoly.x[2]=0;
  371.             MyPoly.y[3]=0;
  372.             MyPoly.y[0]=(GrMaxY()*(i+1))/ROTATIONS;
  373.             MyPoly.y[1]=GrMaxY();
  374.             MyPoly.y[2]=GrMaxY()-(GrMaxY()*(i+1))/ROTATIONS;
  375.             DrawPoly(&MyPoly,WhiteColor);
  376.             DrawTexture(&MyPoly,&MyMap,0);
  377.         }
  378.         for(i=0;i<ROTATIONS;i++)
  379.         {
  380.             rand();
  381.             if(kbhit())
  382.                 break;
  383.             MyPoly.x[2]=(GrMaxX()*(i+1))/ROTATIONS;
  384.             MyPoly.x[3]=GrMaxX();
  385.             MyPoly.x[0]=GrMaxX()-(GrMaxX()*(i+1))/ROTATIONS;
  386.             MyPoly.x[1]=0;
  387.             MyPoly.y[2]=0;
  388.             MyPoly.y[3]=(GrMaxY()*(i+1))/ROTATIONS;
  389.             MyPoly.y[0]=GrMaxY();
  390.             MyPoly.y[1]=GrMaxY()-(GrMaxY()*(i+1))/ROTATIONS;
  391.             DrawPoly(&MyPoly,RedColor);
  392.             DrawTexture(&MyPoly,&MyMap,0);
  393.         }
  394.         for(i=0;i<ROTATIONS;i++)
  395.         {
  396.             rand();
  397.             if(kbhit())
  398.                 break;
  399.             MyPoly.x[1]=(GrMaxX()*(i+1))/ROTATIONS;
  400.             MyPoly.x[2]=GrMaxX();
  401.             MyPoly.x[3]=GrMaxX()-(GrMaxX()*(i+1))/ROTATIONS;
  402.             MyPoly.x[0]=0;
  403.             MyPoly.y[1]=0;
  404.             MyPoly.y[2]=(GrMaxY()*(i+1))/ROTATIONS;
  405.             MyPoly.y[3]=GrMaxY();
  406.             MyPoly.y[0]=GrMaxY()-(GrMaxY()*(i+1))/ROTATIONS;
  407.             DrawPoly(&MyPoly,WhiteColor);
  408.             DrawTexture(&MyPoly,&MyMap,0);
  409.         }
  410.     }
  411.     while(kbhit())
  412.         getch();
  413.     while(!kbhit())
  414.     {
  415.         rand();
  416.         for(i=0;i<20;i++)
  417.         {
  418.             rand();
  419.             if(kbhit())
  420.                 break;
  421.             MyPoly.x[0]=0-(i*8);
  422.             MyPoly.x[1]=GrMaxX()+(i*8);
  423.             MyPoly.x[2]=GrMaxX()+(i*8);
  424.             MyPoly.x[3]=0-(i*8);
  425.             MyPoly.y[0]=0-(i*8);
  426.             MyPoly.y[1]=0-(i*8);
  427.             MyPoly.y[2]=GrMaxY()+(i*8);
  428.             MyPoly.y[3]=GrMaxY()+(i*8);
  429.             /* DrawPoly(&MyPoly,RedColor); */
  430.             DrawTexture(&MyPoly,&MyMap,0);
  431.         }
  432.         for(i=20;i;i--)
  433.         {
  434.             rand();
  435.             if(kbhit())
  436.                 break;
  437.             MyPoly.x[0]=0-(i*8);
  438.             MyPoly.x[1]=GrMaxX()+(i*8);
  439.             MyPoly.x[2]=GrMaxX()+(i*8);
  440.             MyPoly.x[3]=0-(i*8);
  441.             MyPoly.y[0]=0-(i*8);
  442.             MyPoly.y[1]=0-(i*8);
  443.             MyPoly.y[2]=GrMaxY()+(i*8);
  444.             MyPoly.y[3]=GrMaxY()+(i*8);
  445.             /* DrawPoly(&MyPoly,RedColor); */
  446.             DrawTexture(&MyPoly,&MyMap,0);
  447.         }
  448.     }
  449.     while(kbhit())
  450.         getch();
  451.     i=1;
  452.     j=2;
  453.     k=3;
  454.     NewY=0;   /* Directions of points */
  455.     while(!kbhit())
  456.     {
  457.         MyPoly.x[0]=UpdateX(MyPoly.x[0],i);
  458.         MyPoly.y[0]=UpdateY(MyPoly.y[0],i);
  459.         i=NewDir(MyPoly.x[0],MyPoly.y[0],i);
  460.  
  461.         MyPoly.x[1]=UpdateX(MyPoly.x[1],j);
  462.         MyPoly.y[1]=UpdateY(MyPoly.y[1],j);
  463.         j=NewDir(MyPoly.x[1],MyPoly.y[1],j);
  464.  
  465.         MyPoly.x[2]=UpdateX(MyPoly.x[2],k);
  466.         MyPoly.y[2]=UpdateY(MyPoly.y[2],k);
  467.         k=NewDir(MyPoly.x[2],MyPoly.y[2],k);
  468.  
  469.         MyPoly.x[3]=UpdateX(MyPoly.x[3],NewY);
  470.         MyPoly.y[3]=UpdateY(MyPoly.y[3],NewY);
  471.         NewY=NewDir(MyPoly.x[3],MyPoly.y[3],NewY);
  472.  
  473.         /* memset(RPtr,0,GrSizeX()*GrSizeY()); */
  474.         UnIntersectQuad(&MyPoly);
  475.         DrawTexture(&MyPoly,&MyMap,0);
  476.     }
  477.     while(kbhit())
  478.         getch();
  479.     getch();
  480.     GrSetMode(GR_default_text);
  481. }
  482.  
  483. /*
  484.  * Convenience function... update the direction, if needed
  485.  */
  486. int NewDir(int x,int y,int olddir)
  487. {
  488.     if(x<=0)
  489.     {
  490.         if(y<=0)
  491.         {
  492.             return(3);
  493.         }
  494.         else
  495.         {
  496.             if(y>=GrMaxY())
  497.             {
  498.                 return(1);
  499.             }
  500.             return(RAND(3)+1);
  501.         }
  502.     }
  503.     else
  504.     {
  505.         if(x>=GrMaxX())
  506.         {
  507.             if(y<=0)
  508.             {
  509.                 return(5);
  510.             }
  511.             else
  512.             {
  513.                 if(y>=GrMaxY())
  514.                 {
  515.                     return(7);
  516.                 }
  517.                 return(RAND(3)+5);
  518.             }
  519.         }
  520.         else
  521.         {
  522.             if(y<=0)
  523.             {
  524.                 return(RAND(3)+3);
  525.             }
  526.             else
  527.             {
  528.                 if(y>=GrMaxY())
  529.                 {
  530.                     olddir=RAND(3); if(olddir==2) olddir=7;
  531.                     return(olddir);
  532.                 }
  533.                 return(olddir);
  534.             }
  535.         }
  536.     }
  537. }
  538.  
  539. /*
  540.  * Convenience function... update the X-Co-ord given a direction
  541.  */
  542. int UpdateX(int x,int direction)
  543. {
  544.     switch(direction)
  545.     {
  546.         case 0: /* UP */
  547.         case 4:
  548.             return(x);
  549.             break;
  550.         case 1: /* UP-RIGHT */
  551.         case 2:
  552.         case 3:
  553.             return(x+1);
  554.             break;
  555.         case 5:
  556.         case 6:
  557.         case 7:
  558.             return(x-1);
  559.             break;
  560.     }
  561. }
  562.  
  563. /*
  564.  * Convenience function... update the Y-Co-ord given a direction
  565.  */
  566. int UpdateY(int y,int direction)
  567. {
  568.     switch(direction)
  569.     {
  570.         case 2:
  571.         case 6:
  572.             return(y);
  573.             break;
  574.         case 0: /* UP */
  575.         case 1: /* UP-RIGHT */
  576.         case 7:
  577.             return(y-1);
  578.             break;
  579.         case 3:
  580.         case 4:
  581.         case 5:
  582.             return(y+1);
  583.             break;
  584.     }
  585. }
  586.  
  587. /*
  588.  *  Program the RAMDAC 256-color palette. Seems like I'm _ALWAYS_ re-inventing
  589.  *   this one!
  590.  */
  591. void setcolor(unsigned char c,unsigned char r,unsigned char g,unsigned char b)
  592. {
  593.     disable();
  594.     outportb(0x3c8,c);
  595.     inportb(0x80);
  596.     outportb(0x3c9,r);
  597.     inportb(0x80);
  598.     outportb(0x3c9,g);
  599.     inportb(0x80);
  600.     outportb(0x3c9,b);
  601.     enable();
  602. }
  603.  
  604. /*
  605.  *  Fragment from my game/sprite system. Wraps a call to load a gif.
  606.  *   Sorry, but these routines will have to be replaced if you want to
  607.  *   directly compile it. Your best bet is to track down "GIFLIB" which
  608.  *   contains libraries and source for encoding/decoding gifs. It can
  609.  *   be converted to 32-Bit without toooo much pain (I managed it...)
  610.  */
  611. int LoadSlot(int sl,char *fname)
  612. {
  613.     GifFileType GifFile;
  614.     unsigned char *ptr1;
  615.     unsigned char *ptr2;
  616.  
  617.     if(LoadGif(7,fname,&ptr1,(GifColorType **)&ptr2,&GifFile))
  618.     {
  619.         return(-1);
  620.     }
  621.     /* Load was successful... */
  622.     if(slots[sl].pal)
  623.     {
  624.         free(slots[sl].pal);
  625.     }
  626.     if(slots[sl].buff)
  627.     {
  628.         free(slots[sl].buff);
  629.     }
  630.     strcpy(slots[sl].filename,fname);
  631.     slots[sl].buff=ptr1;
  632.     slots[sl].pal=ptr2;
  633.     slots[sl].sizex=GifFile.SWidth;
  634.     slots[sl].sizey=GifFile.SHeight;
  635.     return(0);
  636. }
  637.  
  638. /*
  639.  *  Return an array of vector IDs sorted by Y value
  640.  */
  641. void OrderPoly(struct quad_s *poly,unsigned char *order)
  642. {
  643.     int i,j,x,y;
  644.  
  645.     for(i=0;i<4;i++)
  646.     {
  647.         order[i]=(unsigned char)i;
  648.     }
  649.     for(i=0;i<3;i++)
  650.     {
  651.         for(j=(i+1);j<4;j++)
  652.         {
  653.             if(poly->y[order[j]]<poly->y[order[i]])
  654.             {
  655.                 x=order[i]; order[i]=order[j]; order[j]=x;
  656.             }
  657.         }
  658.     }
  659. }
  660.  
  661.  
  662. /*
  663.  *  General purpose linear conversion routine
  664.  *  I use a more complex version at work that reduces precision to prevent
  665.  *  overflows.
  666.  */
  667. long lconvert(long a,long b,long c)
  668. {
  669.     if(b)
  670.     {
  671.         return((a*c)/b);
  672.     }
  673.     return(0);
  674. }
  675.  
  676. /*
  677.  * Return an arbitrary X point on a given line
  678.  */
  679. int XPoint(int x1,int y1,int x2,int y2,int ny)
  680. {
  681.     int z;
  682.  
  683.     x2-=x1;
  684.     y2-=y1;
  685.     ny-=y1;
  686.     z=lconvert(x2,y2,ny);
  687.     return(z+x1);
  688. }
  689.  
  690. /*
  691.  * Return an arbitrary Y point on a given line
  692.  */
  693. int YPoint(int x1,int y1,int x2,int y2,int nx)
  694. {
  695.     int z;
  696.  
  697.     x2-=x1;
  698.     y2-=y1;
  699.     nx-=x1;
  700.     z=lconvert(y2,x2,nx);
  701.     return(z+y1);
  702. }
  703.  
  704. /*
  705.  * Returns a floating point version of a 16.16 signed fixed point number
  706.  */
  707. float fixed2float(long z)
  708. {
  709.     int sign;
  710.     unsigned long whole,fraction;
  711.     float result;
  712.  
  713.     sign=0;
  714.     if(z<0)
  715.     {
  716.         sign=1;
  717.         z=0-z;
  718.     }
  719.     whole=z>>16;
  720.     fraction=z&0x0ffff;
  721.     result=(float)(fraction); result/=65536.0;
  722.     result+=(float)(whole);
  723.     if(sign) result=0.0-result;
  724.     return(result);
  725. }
  726.  
  727. /*
  728.  * What we do, is for each Screen Y, we draw a line of texture
  729.  *
  730.  *
  731.  * This routine cannot handle "horizontal convexity", that is, when we
  732.  * get two chunks to draw on the same scan line. The program will freak out,
  733.  * so "UnIntersectQuad" is used to "remove" the convexity... normally, you
  734.  * would just avoid this situation. Likewise, the routine doesn't like
  735.  * intersections too much, but surprisingly, the program won't blow any
  736.  * serious chunks, as long as the convexity is taken care of. Images can
  737.  * be flipped, by re-ordering the corners of your polygon.
  738.  * Polygon Co-ordinates can range from -32768 to 32767, as I use SIGNED
  739.  * 16.16bit fixed point numbers.
  740.  *
  741.  *
  742.  */
  743. void DrawTexture(struct quad_s *poly,struct text_s *Texture,int debug)
  744. {
  745.     long i,j,k,ysize;
  746.     long LeftVectorA,LeftVectorB,RightVectorA,RightVectorB;
  747.     long YCheck,LeftSegment,RightSegment,m,n,o,p,q,OSize;
  748.     long LeftDelta,LeftStartX,RightDelta;
  749.     long L_Size,R_Size,LeftBDeltaX,LeftBDeltaY;
  750.     long RightBDeltaX,RightBDeltaY,RightXPos,RightYPos;
  751.     long LeftXPos,LeftYPos,LeftCount,RightCount,LeftX,RightX;
  752.     unsigned char *screenptr;
  753.  
  754.     lcount=rcount=1;
  755.     OrderPoly(poly,Order);  /* Order now holds points from top to bottom */
  756.     ysize=poly->y[Order[3]]-poly->y[Order[0]];    /* Total screen Y Size */
  757.     YZSize=ysize;
  758.     if(ysize<3)                     /* Don't even try if too small */
  759.         return;
  760.     YCheck=poly->y[Order[3]];               /* 'Lowest' Y+some amount */
  761.     /* Now, load data for first two segments... */
  762.     screenptr=ScreenPtr;
  763.     i=GrSizeX()*poly->y[Order[0]];
  764.     screenptr+=i;
  765.     i=0; j=0;  k=0;
  766.     m=(Order[0]+1)%4; n=(Order[0]+3)%4;
  767.     while(i==j && k<3)
  768.     {
  769.         YCheck+=20;
  770.         i=XPoint(poly->x[Order[0]],poly->y[Order[0]],
  771.                 poly->x[m],poly->y[m],YCheck);
  772.         j=XPoint(poly->x[Order[0]],poly->y[Order[0]],
  773.                 poly->x[n],poly->y[n],YCheck);
  774.         k++;
  775.     }
  776.     if(k==3)
  777.     {
  778.         /* Either, invalid, or flat line! */
  779.         i=poly->x[m];  j=poly->x[n];
  780.         if(i==j)
  781.             return;  /* Invalid polygon... */
  782.     }
  783.     LeftVectorA=Order[0];
  784.     RightVectorA=Order[0];
  785.     if(i<j)  /* 0,m is LEFT edge */
  786.     {
  787.         LeftVectorB=m; RightVectorB=n;
  788.         LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  789.         RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  790.         L_Size=LeftCount;
  791.         R_Size=RightCount;
  792.         i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  793.         LeftDelta=lconvert(i,LeftCount,65536);
  794.         j=poly->x[RightVectorB]-poly->x[RightVectorA];
  795.         RightDelta=lconvert(j,RightCount,65536);
  796.         LeftX=poly->x[LeftVectorA]*65536;
  797.         RightX=LeftX;
  798.     }
  799.     else
  800.     {
  801.         LeftVectorB=n; RightVectorB=m;
  802.         LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  803.  
  804.         RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  805.         L_Size=LeftCount;
  806.         R_Size=RightCount;
  807.         i=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  808.         LeftDelta=lconvert(i,LeftCount,65536);
  809.  
  810.         j=poly->x[RightVectorB]-poly->x[RightVectorA];
  811.         RightDelta=lconvert(j,RightCount,65536);
  812.         LeftX=poly->x[LeftVectorA]*65536;
  813.         RightX=LeftX;
  814.     }
  815.     switch((LeftVectorA<<2)|LeftVectorB)
  816.     {
  817.         case 0: /* A-A Impossible */
  818.         case 2: /* A-C Impossible */
  819.         case 5: /* B-B Impossible */
  820.         case 7: /* B-D Impossible */
  821.         case 8: /* C-A Impossible */
  822.         case 10: /* C-C Impossible */
  823.         case 13: /* D-B impossible */
  824.         case 15: /* D-D Impossible */
  825.             break;
  826.         case 1: /* A-B */
  827.             LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  828.             LeftBDeltaY=0;
  829.             LeftXPos=0; LeftYPos=0;
  830.             break;
  831.         case 3: /* A-D */
  832.             LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  833.             LeftBDeltaX=0;
  834.             LeftXPos=0; LeftYPos=0;
  835.             break;
  836.         case 4: /* B-A */
  837.             LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  838.             LeftBDeltaY=0;
  839.             LeftXPos=Texture->XSize-1; LeftYPos=0;
  840.             break;
  841.         case 6: /* B-C */
  842.             LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  843.             LeftBDeltaX=0;
  844.             LeftXPos=Texture->XSize-1; LeftYPos=0;
  845.             break;
  846.         case 9: /* C-B */
  847.             LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  848.             LeftBDeltaX=0;
  849.             LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  850.             break;
  851.         case 11: /* C-D */
  852.             LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  853.             LeftBDeltaY=0;
  854.             LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  855.             break;
  856.         case 12: /* D-A */
  857.             LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  858.             LeftBDeltaX=0;
  859.             LeftXPos=0; LeftYPos=Texture->YSize-1;
  860.             break;
  861.         case 14: /* D-C */
  862.             LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  863.             LeftBDeltaY=0;
  864.             LeftXPos=0; LeftYPos=Texture->YSize-1;
  865.             break;
  866.     }
  867.     switch((RightVectorA<<2)|RightVectorB)
  868.     {
  869.         case 0: /* A-A Impossible */
  870.         case 2: /* A-C Impossible */
  871.         case 5: /* B-B Impossible */
  872.         case 7: /* B-D Impossible */
  873.         case 8: /* C-A Impossible */
  874.         case 10: /* C-C Impossible */
  875.         case 13: /* D-B impossible */
  876.         case 15: /* D-D Impossible */
  877.             break;
  878.         case 1: /* A-B */
  879.             RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  880.             RightBDeltaY=0;
  881.             RightXPos=0; RightYPos=0;
  882.             break;
  883.         case 3: /* A-D */
  884.             RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  885.             RightBDeltaX=0;
  886.             RightXPos=0; RightYPos=0;
  887.             break;
  888.         case 4: /* B-A */
  889.             RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  890.             RightBDeltaY=0;
  891.             RightXPos=Texture->XSize-1; RightYPos=0;
  892.             break;
  893.         case 6: /* B-C */
  894.             RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  895.             RightBDeltaX=0;
  896.             RightXPos=Texture->XSize-1; RightYPos=0;
  897.             break;
  898.         case 9: /* C-B */
  899.             RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  900.             RightBDeltaX=0;
  901.             RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  902.             break;
  903.         case 11: /* C-D */
  904.             RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  905.             RightBDeltaY=0;
  906.             RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  907.             break;
  908.         case 12: /* D-A */
  909.             RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  910.             RightBDeltaX=0;
  911.             RightXPos=0; RightYPos=Texture->YSize-1;
  912.             break;
  913.         case 14: /* D-C */
  914.             RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  915.             RightBDeltaY=0;
  916.             RightXPos=0; RightYPos=Texture->YSize-1;
  917.             break;
  918.     }
  919.     LeftXPos*=65536; LeftYPos*=65536;
  920.     RightXPos*=65536; RightYPos*=65536;
  921.     lva[0]=LeftVectorA;
  922.     lvb[0]=LeftVectorB;
  923.     rva[0]=RightVectorA;
  924.     rvb[0]=RightVectorB;
  925.     lcnt[0]=LeftCount;
  926.     rcnt[0]=RightCount;
  927.     for(i=0;i<ysize;i++)
  928.     {
  929.         m=poly->y[Order[0]]+i;
  930.         if(m>GrMaxY())
  931.             break;
  932.         if(!LeftCount)
  933.         {
  934.             /* Get next Left Vector */
  935.             j=LeftVectorB; k=(LeftVectorB+1)%4;
  936.             if(k==LeftVectorA)
  937.             {
  938.                 k=(LeftVectorB+3)%4;
  939.             }
  940.             LeftVectorA=j; LeftVectorB=k;
  941.             LeftX=poly->x[LeftVectorA]*65536;
  942.             LeftCount=poly->y[LeftVectorB]-poly->y[LeftVectorA];
  943.             lva[lcount]=LeftVectorA;
  944.             lvb[lcount]=LeftVectorB;
  945.             lcnt[lcount]=LeftCount;
  946.             lcount++;
  947.             j=poly->x[LeftVectorB]-poly->x[LeftVectorA];
  948.             L_Size=LeftCount;
  949.             LeftDelta=lconvert(j,LeftCount,65536);
  950.             switch((LeftVectorA<<2)|LeftVectorB)
  951.             {
  952.                 case 0: /* A-A Impossible */
  953.                 case 2: /* A-C Impossible */
  954.                 case 5: /* B-B Impossible */
  955.                 case 7: /* B-D Impossible */
  956.                 case 8: /* C-A Impossible */
  957.                 case 10: /* C-C Impossible */
  958.                 case 13: /* D-B impossible */
  959.                 case 15: /* D-D Impossible */
  960.                     break;
  961.                 case 1: /* A-B */
  962.                     LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  963.                     LeftBDeltaY=0;
  964.                     LeftXPos=0; LeftYPos=0;
  965.                     break;
  966.                 case 3: /* A-D */
  967.                     LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  968.                     LeftBDeltaX=0;
  969.                     LeftXPos=0; LeftYPos=0;
  970.                     break;
  971.                 case 4: /* B-A */
  972.                     LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  973.                     LeftBDeltaY=0;
  974.                     LeftXPos=Texture->XSize-1; LeftYPos=0;
  975.                     break;
  976.                 case 6: /* B-C */
  977.                     LeftBDeltaY=lconvert(Texture->YSize,L_Size,65536);
  978.                     LeftBDeltaX=0;
  979.                     LeftXPos=Texture->XSize-1; LeftYPos=0;
  980.                     break;
  981.                 case 9: /* C-B */
  982.                     LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  983.                     LeftBDeltaX=0;
  984.                     LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  985.                     break;
  986.                 case 11: /* C-D */
  987.                     LeftBDeltaX=-lconvert(Texture->XSize,L_Size,65536);
  988.                     LeftBDeltaY=0;
  989.                     LeftXPos=Texture->XSize-1; LeftYPos=Texture->YSize-1;
  990.                     break;
  991.                 case 12: /* D-A */
  992.                     LeftBDeltaY=-lconvert(Texture->YSize,L_Size,65536);
  993.                     LeftBDeltaX=0;
  994.                     LeftXPos=0; LeftYPos=Texture->YSize-1;
  995.                     break;
  996.                 case 14: /* D-C */
  997.                     LeftBDeltaX=lconvert(Texture->XSize,L_Size,65536);
  998.                     LeftBDeltaY=0;
  999.                     LeftXPos=0; LeftYPos=Texture->YSize-1;
  1000.                     break;
  1001.             }
  1002.             LeftXPos*=65536; LeftYPos*=65536;
  1003.  
  1004.         }
  1005.         if(!RightCount)
  1006.         {
  1007.             /* Get next Right Vector */
  1008.             j=RightVectorB; k=(RightVectorB+1)%4;
  1009.             if(k==RightVectorA)
  1010.             {
  1011.                 k=(RightVectorB+3)%4;
  1012.             }
  1013.             RightVectorA=j; RightVectorB=k;
  1014.             RightX=poly->x[RightVectorA]*65536;
  1015.             RightCount=poly->y[RightVectorB]-poly->y[RightVectorA];
  1016.             R_Size=RightCount;
  1017.             rva[rcount]=RightVectorA;
  1018.             rvb[rcount]=RightVectorB;
  1019.             rcnt[rcount]=RightCount;
  1020.             rcount++;
  1021.             j=poly->x[RightVectorB]-poly->x[RightVectorA];
  1022.             RightDelta=lconvert(j,RightCount,65536);
  1023.             switch((RightVectorA<<2)|RightVectorB)
  1024.             {
  1025.                 case 0: /* A-A Impossible */
  1026.                 case 2: /* A-C Impossible */
  1027.                 case 5: /* B-B Impossible */
  1028.                 case 7: /* B-D Impossible */
  1029.                 case 8: /* C-A Impossible */
  1030.                 case 10: /* C-C Impossible */
  1031.                 case 13: /* D-B impossible */
  1032.                 case 15: /* D-D Impossible */
  1033.                     break;
  1034.                 case 1: /* A-B */
  1035.                     RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  1036.                     RightBDeltaY=0;
  1037.                     RightXPos=0; RightYPos=0;
  1038.                     break;
  1039.                 case 3: /* A-D */
  1040.                     RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  1041.                     RightBDeltaX=0;
  1042.                     RightXPos=0; RightYPos=0;
  1043.                     break;
  1044.                 case 4: /* B-A */
  1045.                     RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  1046.                     RightBDeltaY=0;
  1047.                     RightXPos=Texture->XSize-1; RightYPos=0;
  1048.                     break;
  1049.                 case 6: /* B-C */
  1050.                     RightBDeltaY=lconvert(Texture->YSize,R_Size,65536);
  1051.                     RightBDeltaX=0;
  1052.                     RightXPos=Texture->XSize-1; RightYPos=0;
  1053.                     break;
  1054.                 case 9: /* C-B */
  1055.                     RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  1056.                     RightBDeltaX=0;
  1057.                     RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  1058.                     break;
  1059.                 case 11: /* C-D */
  1060.                     RightBDeltaX=-lconvert(Texture->XSize,R_Size,65536);
  1061.                     RightBDeltaY=0;
  1062.                     RightXPos=Texture->XSize-1; RightYPos=Texture->YSize-1;
  1063.                     break;
  1064.                 case 12: /* D-A */
  1065.                     RightBDeltaY=-lconvert(Texture->YSize,R_Size,65536);
  1066.                     RightBDeltaX=0;
  1067.                     RightXPos=0; RightYPos=Texture->YSize-1;
  1068.                     break;
  1069.                 case 14: /* D-C */
  1070.                     RightBDeltaX=lconvert(Texture->XSize,R_Size,65536);
  1071.                     RightBDeltaY=0;
  1072.                     RightXPos=0; RightYPos=Texture->YSize-1;
  1073.                     break;
  1074.             }
  1075.             RightXPos*=65536; RightYPos*=65536;
  1076.         }
  1077.         /* Now, We can shoot our row... */
  1078.         j=(LeftXPos/65536); j+=((LeftYPos/65536)*Texture->XSize);
  1079.         /* j=offset into bitmap... */
  1080.         k=(RightX-LeftX)/65536;   /* Size of line... */
  1081.         if(m<0) k=0;  /* Skip if above screen */
  1082.         m=LeftX/65536; n=RightX/65536;
  1083.         if((n<0)||(m>GrMaxX()))
  1084.         {
  1085.             k=0; /* No line to be draw... */
  1086.         }
  1087.         if(k)
  1088.         {
  1089.             OSize=k;
  1090.             p=LeftXPos; q=LeftYPos;
  1091.             o=LeftX/65536;
  1092.             if(m<0)
  1093.             {
  1094.                 if((m+k)>0)  /* Clip Left Boundary */
  1095.                 {
  1096.                     m=-m;
  1097.                     p+=(((RightXPos-LeftXPos)/k)*m);
  1098.                     q+=(((RightYPos-LeftYPos)/k)*m);
  1099.                     o+=m;
  1100.                 }
  1101.                 else
  1102.                     k=0;
  1103.             }
  1104.             if(n>GrMaxX()) /* Clip Right boundary */
  1105.             {
  1106.                 n-=GrMaxX();
  1107.                 k-=n;
  1108.             }
  1109.         }
  1110.         /*
  1111.             This is the "inner" loop. Clipping has already been done.
  1112.             "p" is our fixed point bitmap X position
  1113.             "q" is our fixed point bitmap Y position
  1114.             "m" is our starting screen X position
  1115.         */
  1116.         if(k>2)
  1117.         {
  1118.             m=(RightXPos-LeftXPos)/OSize; n=(RightYPos-LeftYPos)/OSize;
  1119.             /* m and n equal deltas for bitmap ray */
  1120.             if(debug)
  1121.             {
  1122.                 if(getch()==' ')
  1123.                 {
  1124.                     GrSetMode(GR_default_text);
  1125.                     printf("XInc= %f  YInc=%f OSize=%d",fixed2float(m),
  1126.                         fixed2float(n),OSize);
  1127.                     printf("ScreenPos=%d P=%f Q=%f\n",o,
  1128.                         fixed2float(p),fixed2float(q));
  1129.  
  1130.                     printf("LeftX=%f  RightX=%f ",fixed2float(LeftXPos),
  1131.                         fixed2float(RightXPos));
  1132.                     printf("LeftY=%f  RightY=%f ",fixed2float(LeftYPos),
  1133.                         fixed2float(RightYPos));
  1134.                     printf("(%c-%c)/(%c-%c)\n",
  1135.                         LeftVectorA+'A',LeftVectorB+'A',RightVectorA+'A',
  1136.                         RightVectorB+'A');
  1137.                     printf(
  1138.                      "L_Size=%d R_Size=%d LeftCount=%d RightCount=%d\n",
  1139.                        L_Size,R_Size,LeftCount,RightCount);
  1140.                     printf("A(%d,%d) B(%d,%d) C(%d,%d) D(%d,%d)\n",
  1141.                         poly->x[0],poly->y[0],poly->x[1],poly->y[1],
  1142.                         poly->x[2],poly->y[2],poly->x[3],poly->y[3]);
  1143.                     exit(0);
  1144.                 }
  1145.             }
  1146.             for(;k;k--,o++)
  1147.             {
  1148.                 j=(p/65536); j+=((q/65536)*Texture->XSize);
  1149.                 screenptr[o]=Texture->Buffer[j];
  1150.                 p+=m; q+=n;
  1151.             }
  1152.         }
  1153.         /* Ending position in bitmap... */
  1154.         LeftCount--; RightCount--;
  1155.         RightXPos+=RightBDeltaX;
  1156.         RightYPos+=RightBDeltaY;
  1157.         LeftXPos+=LeftBDeltaX;
  1158.         LeftYPos+=LeftBDeltaY;
  1159.         LeftX+=LeftDelta;
  1160.         RightX+=RightDelta;
  1161.         screenptr+=GrSizeX();
  1162.  
  1163.     }
  1164.  
  1165. }
  1166.  
  1167.  
  1168.  
  1169.